import json
from travel_game.models import *
from django.template.loader import Template, Context
from django.contrib.auth import authenticate
from django.contrib.auth import login as djangoLogin, logout as djangoLogout
from django.shortcuts import render_to_response
from django.contrib.auth.decorators import login_required
from django.core.context_processors import csrf
from django.http import HttpResponse, HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.template import RequestContext
from travel_game.forms import teamInfoForm, paceForm, rationForm



@login_required
def startUp(request):
    '''
    Function to load initial form to create a new game
    Inputs: request
    Outputs: Rendered HTTP response
    request: A Django HTTPRequest object with all client info
    '''
    # Create empty context dictionary for rendering the template
    context = {}
    context.update(csrf(request))
    # create unbound teamInfoForm and place in context dictionary
    context['teamInfoForm'] = teamInfoForm()
    # render startUpMenu template and return to the user
    return render_to_response('html/startUpMenu.html',context,context_instance=RequestContext(request))

@login_required
def acceptTeamInfo(request):
    '''
    Function to handle startUpMenu data to initialize a party
    Inputs: request
    Outputs: Rendered HTTP response
    '''
    # create empty context dictionary for rendering the template
    context = {}
    context.update(csrf(request))
    
    # check if POST data was submitted (should only access this view via post)
    if request.method == 'POST':
        # load form data from client into a bound form instance of teamInfoForm
        print request.POST["startDate"]
        infoForm = teamInfoForm(request.POST)
        if infoForm.is_valid(): # if form data is valid, deal with it
            # create a new game and associate it with the user
            newGame = OTG(player=request.user)
            newGame.save()
            
            # create a new party for the user's game
            newParty = createParty(infoForm,newGame)

            
            # create all the members, main member first
            createCharacter(infoForm.cleaned_data['mainCharacter'],newParty,True)
            for i in range(1,5):
                currName = infoForm.cleaned_data['teamMember' + str(i)]
                createCharacter(currName,newParty,False)
            createWagon(newParty)
            request.session['currentGame']=newGame
            request.session['atStore']=True
            return HttpResponse(reverse('travel_game.views.locationHandler'))
        else: # if form data is not valid, return form with errors to user
            context['error']=True
            
        # render some short HTML of just the form
        context['teamInfoForm']=infoForm
        t = Template('{{ teamInfoForm.as_p }}{% if error %}<div id="error"></div>{% endif %}{% csrf_token %}<button id="continue" type="button" url="{% url travel_game.views.acceptTeamInfo %}" onclick="submitTeamInfo(this);">Go!</button>')
        return HttpResponse(t.render(Context(context)))

def login(request):
    '''
    function to log a user in
    inputs: request
    outputs: 
    '''
    context = {}
    context.update(csrf(request))
    if request.method=='POST': # if data was posted, attempt to log user in
        # try to authenticate user using given username and password
        user = authenticate(username=request.POST['username'],password=request.POST['pwd'])
        if user is not None: # if user is logged in, log them in with django's auth system
            djangoLogin(request,user)
            # redirect to whatever url the user was trying to access
            #return HttpResponseRedirect(request.POST['next'])  # this line redirects to whatever page the unathenticated user
            # requested
            request.session['atStore'] = False
            if (OTG.objects.filter(player=user)):
                return HttpResponseRedirect(reverse('travel_game.views.currentGames'))
            else:
                return HttpResponseRedirect(reverse('travel_game.views.startUp'))
    # if the login failed or nothing was posted, redirect back to the login page
    return render_to_response('html/login.html',context,context_instance=RequestContext(request))

def currentGames(request):
    context = {'allGames':OTG.objects.filter(player=request.user)}
    return render_to_response('html/chooseGame.html',context,context_instance=RequestContext(request))

def createParty(infoForm,newGame):
    newParty = Party(
     distanceFromStart=0,
     profession=infoForm.cleaned_data['profession'],
     game=newGame,
     rations=infoForm.cleaned_data['rations'],
     pace=infoForm.cleaned_data['pace'],
     money=infoForm.cleaned_data['profession'].startingMoney,
     date=infoForm.cleaned_data['startDate']
    )
    newParty.save()
    return newParty

def createWagon(newParty):
    newWagon = Wagon(
        name = 'Wagon',
        health = 10,
        party=newParty,
        isMain = False,
        kind = WAGON,
        carryWeight = WAGON_WEIGHT 
    )
    newWagon.save()

def createCharacter(currName,newParty,main):
    newMember = Member(
    name = currName,
    health = 10,
    party=newParty, 
    isMain = main,
    kind = CHARACTER,
    carryWeight = CHARACTER_WEIGHT                    
    )
    newMember.save()

def loadGame(request,gameID=None):
    if gameID:
        request.session['currentGame']=OTG.objects.get(id=gameID)
        return locationHandler(request)
    else:
        return HttpResponseRedirect(reverse('travel_game.views.currentGames'))
    
    
def createStore(currGame):
    abstractStore = AbstractStore.objects.get(location=Landmark.objects.filter(distanceFromStart=currGame.party_set.all()[0].distanceFromStart))
    if not (abstractStore.store_set.filter(game=currGame)):
        newStore = Store(templateStore=abstractStore,game=currGame)
        newStore.save()
        for item in abstractStore.item_set.all():
            newItem = Item(itemType=item.itemType,quantity=item.quantity,holder=newStore)
            newItem.save()
            
    else:
        newStore = Store.objects.get(templateStore=abstractStore,game=currGame)
    
    return newStore

@login_required
def leaveLandmark(request):
    move(request)
    return HttpResponseRedirect(reverse('travel_game.views.dayAction'))
    
def dayAction(request):
    if atLandmark(request):
        return HttpResponseRedirect(reverse('travel_game.views.locationHandler'))
    context = {}
    context.update(csrf(request))
    context['party'] = request.session['currentGame'].party_set.all()[0]
    food = context['party'].item_set.filter(itemType__name='Food')
    if food:
        food = food[0]
    context['food'] = food.quantity * food.itemType.weight
    context['paceForm']=paceForm()
    context['rationForm']=rationForm()
    return render_to_response('html/normalDay.html',context,context_instance=RequestContext(request))

def changePace(request): 
    paceFormInstance=paceForm(request.GET)
    if paceFormInstance.is_valid(): 
        pace = paceFormInstance.cleaned_data['pace']
        currParty = request.session['currentGame'].party_set.all()[0]
        currParty.pace=pace
        currParty.save()
    return HttpResponse(pace)

def changeRations(request):
    rationFormInstance=rationForm(request.GET)
    if rationFormInstance.is_valid():
        rations = rationFormInstance.cleaned_data['rations']
        currParty = request.session['currentGame'].party_set.all()[0]
        currParty.rations=rations
        currParty.save()
    return HttpResponse(rations)

def initProfession(request):
    pass

def logout(request):
    djangoLogout(request)
    return HttpResponseRedirect(reverse('travel_game.views.login'))

def createOx(currentGame):
    newMember = Member(
        name = 'Ox',
        health = 10,
        party=currentGame.party_set.all()[0],
        isMain = False,
        kind = OX,
        carryWeight = OX_WEIGHT                    
    )
    newMember.save()

def updatePartyItem(currentGame,itemID,amount,currStore):
    amount = int(amount)
    thisParty = currentGame.party_set.all()[0]
    thisItem = thisParty.item_set.all().filter(itemType__pk=itemID)
    if AbstractItem.objects.get(pk=itemID).name=='Two Oxen':
        numberToCreate = amount * 2
        for i in range(0,numberToCreate):
            createOx(currentGame)
    else:
        if (thisItem):
            thisItem = thisItem[0]
            thisItem.quantity = thisItem.quantity + amount
        else:
            thisItem = Item(itemType=AbstractItem.objects.get(pk=itemID),quantity=amount,holder=thisParty)
        thisItem.save()
        
    storeItem = currStore.item_set.get(itemType__pk=itemID)
    storeItem.quantity = storeItem.quantity - amount
    storeItem.save()
    thisParty.money = thisParty.money - (AbstractItem.objects.get(pk=itemID).cost * amount)
    thisParty.save()
    
def getTotalWeight(currParty):
    totalWeight = 0
    for currItem in currParty.item_set.all():
        totalWeight = totalWeight + (currItem.itemType.weight * currItem.quantity)
    return totalWeight
    
@login_required
def renderStore(request):
    context={}
    context.update(csrf(request))
    currStore = createStore(request.session['currentGame'])
    context['storeItems']=currStore.item_set.all()
    request.session['atStore']=True
    weightCap = 0
    for currMember in request.session['currentGame'].party_set.all()[0].member_set.all():
        weightCap = weightCap + currMember.carryWeight
    weightCap = weightCap - getTotalWeight(request.session['currentGame'].party_set.all()[0])
    context['partyWeightCap']=weightCap
    context['money']=request.session['currentGame'].party_set.all()[0].money
    context['numItems']=len(context['storeItems'])
    return render_to_response('html/store.html',context,context_instance=RequestContext(request))

@login_required
def buyItems(request):
    context={}
    context.update(csrf(request))
    currStore = createStore(request.session['currentGame'])
    if request.method=='POST':
        for itemID, value in request.POST.iteritems():
            if (not itemID=='csrfmiddlewaretoken'):
                updatePartyItem(request.session['currentGame'],itemID, value,currStore)
            request.session['atStore']=False
        return locationHandler(request)
    
@login_required
def sidebarView(request):
    context = {}
        
    return  render_to_response('html/sidebar.html',context,context_instance=RequestContext(request))  

@login_required
def locationHandler(request):
    if request.session['atStore']:
        return HttpResponseRedirect(reverse('travel_game.views.renderStore'))
    elif atLandmark(request):
        return HttpResponseRedirect(reverse('travel_game.views.landmarkAction'))
    else:
        return HttpResponseRedirect(reverse('travel_game.views.dayAction'))
    
def atLandmark(request):
    if Landmark.objects.filter(distanceFromStart=request.session['currentGame'].party_set.all()[0].distanceFromStart):
        return True
    else:
        return False
    
def landmarkAction(request):
#    request.session['atLandmark']=False
#    return locationHandler(request)
    context={}
    return render_to_response('html/independenceLandmark.html',context,context_instance=RequestContext(request))

@login_required
def move(request):
    currParty = request.session['currentGame'].party_set.all()[0]
    food = currParty.item_set.filter(itemType__name='Food')
    numCharacters = currParty.member_set.filter(kind=CHARACTER).count()
    foodConsumed = numCharacters*currParty.rations
    if food:
        food = food[0]
        food.quantity = food.quantity - foodConsumed
        if food.quantity<=0:
            food.quantity=0
        food.save()
    
    if (currParty.pace == 1):
        milesTraveled = 5
        currParty.distanceFromStart = currParty.distanceFromStart+milesTraveled
    elif (currParty.pace==2):
        milesTraveled = 10
        currParty.distanceFromStart = currParty.distanceFromStart+milesTraveled
    elif(currParty.pace==3):
        milesTraveled = 15
        currParty.distanceFromStart = currParty.distanceFromStart+milesTraveled
    currParty.save()
        
    previousLandmarks= Landmark.objects.filter(distanceFromStart__lt=currParty.distanceFromStart)
    for currLandmark in previousLandmarks:
        if ((currParty.distanceFromStart - currLandmark.distanceFromStart) < milesTraveled):
            currParty.distanceFromStart = currLandmark.distanceFromStart
            currParty.save()
            output={'url':reverse('travel_game.views.locationHandler')}
            break
        else:
            output={'distTraveled':currParty.distanceFromStart,'currFood':food.quantity}
    return HttpResponse(json.dumps(output))


    
